#**************************************************************************
#*********************---------------------------------**********************
#********************|    Copyright (c) 2003 - 2022    |*********************
#********************|      by VIRE Technologies.        |*********************
#********************|       All Rights Reserved           |*********************
#*********************---------------------------------**********************
#**************************************************************************
#
# If any question, please write to VIRE Technologies for
# more information:
#			Techart Plaza, A16, No.30 XueYuan Road,
#			Haidian District Beijing 100083,
#			P.R. China
#
# For more, please visit company website: www.vire.cn
#**************************************************************************

find_package(Sphinx)

if (SPHINX_FOUND)
   execute_process(COMMAND "${SPHINX_EXECUTABLE}" --version
                   OUTPUT_VARIABLE SPHINX_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
   string(REGEX REPLACE ".* ([0-9]\\.([0-9]\\.[0-9])?)" "\\1"
          SPHINX_VERSION "${SPHINX_VERSION}")
   message(STATUS "Sphinx version: ${SPHINX_VERSION}")

   # Sphinx base data directory.
   set(WSF_SPHINX_DIR "${CMAKE_CURRENT_LIST_DIR}/sphinx")

   # Path to themes and theme.conf.
   if (NOT SPHINX_THEME_DIR)
      set(SPHINX_THEME_DIR "${CMAKE_BINARY_DIR}/documentation")
   endif()

   if (NOT SPHINX_THEME_NAME)
      set(SPHINX_THEME_NAME "wsftheme")
   endif()

   if (NOT WSF_SPHINX_SIDEBAR_LOGO)
      set(WSF_SPHINX_SIDEBAR_LOGO "${WSF_SPHINX_DIR}/_static/sidebar_logo.png")
   endif()

   if (NOT WSF_SPHINX_FAVICON)
      set(WSF_SPHINX_FAVICON "${WSF_SPHINX_DIR}/_static/favicon.ico")
   endif()

   # Path to extensions and extras.
   set(SPHINX_EXTENSIONS_DIR "${WSF_SPHINX_DIR}/extensions")

   # configured documentation tools and intermediate build results
   set(SPHINX_BUILD_DIR "${CMAKE_BINARY_DIR}/documentation")

   # configured documentation tools and intermediate build results
   set(BINARY_BUILD_DIR "${CMAKE_BINARY_DIR}/documentation/_build")

   # Sphinx cache with pickled ReST documents
   set(SPHINX_CACHE_DIR "${CMAKE_BINARY_DIR}/documentation/_doctrees")

   # HTML output directory
   set(SPHINX_HTML_DIR "${CMAKE_BINARY_DIR}/documentation/html")

   # When "clean" target is run, remove the Sphinx build directory
   set_property(DIRECTORY APPEND PROPERTY
                ADDITIONAL_MAKE_CLEAN_FILES
                "${SPHINX_CACHE_DIR}"
                "${BINARY_BUILD_DIR}"
                "${SPHINX_HTML_DIR}"
               )
else()
   if(WSF_INSTALL_DOCUMENTATION)
      message(WARNING "Sphinx install selected but Sphinx exe not available for generation.")
   endif()
endif()

# Global property to contain WSF sub-project and extension Sphinx inputs
# Always enabled as it is used by other CMake files
define_property(GLOBAL PROPERTY WSF_SPHINX_INPUT
                BRIEF_DOCS "Input for Sphinx"
                FULL_DOCS "Paths to files and directories that will passed to the Sphinxfile INPUT variable"
               )
# Global property to contain WSF sub-project and extension Sphinx input exclusions
# Always enabled as it is used by other CMake files
#define_property(GLOBAL PROPERTY WSF_SPHINX_EXCLUDE
#                BRIEF_DOCS "Exclude for Sphinx"
#                FULL_DOCS "Paths to files and directories that will be excluded from Sphinx INPUT"
#               )
define_property(GLOBAL PROPERTY WSF_SPHINX_SIDEBAR_EXTS
                BRIEF_DOCS "Sidebar Extensions for Sphinx"
                FULL_DOCS "Sidebar extensions names for Sphinx"
               )

define_property(GLOBAL PROPERTY WSF_SPHINX_SIDEBAR_PATHS
                BRIEF_DOCS "Sidebar Extensions paths for Sphinx"
                FULL_DOCS "Sidebar extension paths for Sphinx"
               )

###########################################################
# Macros
###########################################################

# Add the supplied list of directories or files (SPHINX_INPUT) to the global
# list of files that will be used to generate Sphinx documentation
# if they have not already been added. This macro should be called by WSF
# extensions to add documentation to the WSF build.
macro(add_wsf_doc_input SPHINX_INPUT)
   # Store global WSF_SPHINX_INPUT in a local variable for comparison
   get_property(CURRENT_SPHINX_INPUT GLOBAL PROPERTY WSF_SPHINX_INPUT)

   # Loop over the supplied dirs/files and add them one at a time. Because
   # we are expecting lists we use the built in ARGV variable that hold the
   # list of all variables passed in, not SPHINX_INPUT which would only hold
   # the first
   foreach(INPUT_SOURCE ${ARGV})
      # Only add things to INPUT list that are not already there
      get_filename_component(INPUT_SOURCE ${INPUT_SOURCE} ABSOLUTE)
      if(NOT (CURRENT_SPHINX_INPUT MATCHES "${INPUT_SOURCE};"))
         # NOTES: APPEND_STRING is used to build a string ; separated list that is
         # passed to the conf.py.in to create the conf.py.
         set_property(GLOBAL APPEND_STRING PROPERTY WSF_SPHINX_INPUT "${INPUT_SOURCE};")
      endif()
   endforeach()
endmacro()

# Add the supplied sidebar items in html format to the sidebar list.
# if they have not already been added. This macro should be called by WSF
# extensions to add sidebar items to the WSF build.
macro(add_wsf_doc_sidebar_ext SPHINX_SIDEBAR_EXT)
   # Store global WSF_SPHINX_SIDEBAR_EXTS in a local variable for comparison
   get_property(CURRENT_SPHINX_THEME_PATHS GLOBAL PROPERTY WSF_SPHINX_SIDEBAR_EXTS)

   # Loop over the supplied dirs/files and add them one at a time. Because
   # we are expecting lists we use the built in ARGV variable that hold the
   # list of all variables passed in, not SPHINX_THEME_PATH which would only hold
   # the first
   foreach(SIDEBAR_FILE ${ARGV})
      # Only add things to THEME path list that are not already there
      get_filename_component(SIDEBAR_PATH ${SIDEBAR_FILE} ABSOLUTE)
      get_filename_component(SIDEBAR_DIR ${SIDEBAR_PATH} DIRECTORY)
      get_filename_component(SIDEBAR_FILE ${SIDEBAR_PATH} NAME)
      if(NOT (CURRENT_SPHINX_THEME_PATHS MATCHES "'${SIDEBAR_FILE}', "))
         # NOTES: APPEND_STRING is used to build a string, separated list that is
         # passed to the conf.py.in to create the conf.py.
         set_property(GLOBAL APPEND_STRING PROPERTY WSF_SPHINX_SIDEBAR_EXTS "'${SIDEBAR_FILE}', ")
         set_property(GLOBAL APPEND_STRING PROPERTY WSF_SPHINX_SIDEBAR_PATHS "${SIDEBAR_DIR};")
      endif()
   endforeach()
endmacro()

set(DOCUMENTATION_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}")

macro(create_doctarget)
   if (SPHINX_FOUND)
      set_property(GLOBAL APPEND_STRING PROPERTY WSF_SPHINX_SIDEBAR_PATHS "${WSF_SPHINX_DIR}/wsftheme;")
      get_property(SPHINX_SIDEBAR_PATHS GLOBAL PROPERTY WSF_SPHINX_SIDEBAR_PATHS)
      add_custom_target(DOCUMENTATION
                        COMMAND
                        ${CMAKE_COMMAND}
                        -E copy_directory
                        ${SPHINX_SIDEBAR_PATHS}
                        ${SPHINX_THEME_DIR}/wsftheme
                        COMMENT "Copying Themes with CMake into ${SPHINX_THEME_DIR}/wsftheme"
                        WORKING_DIRECTORY ${SPHINX_BUILD_DIR}
                        SOURCES ${DOCUMENTATION_LIST_FILE} "${SPHINX_BUILD_DIR}/index.html"
                       )
      set_property(TARGET DOCUMENTATION PROPERTY FOLDER CMakeTargets)

      add_custom_command(TARGET DOCUMENTATION POST_BUILD
                         COMMAND
                         ${SPHINX_EXECUTABLE}
                         -q -b html
                         -c "${SPHINX_BUILD_DIR}"
                         -d "${SPHINX_CACHE_DIR}"
                         -w ${SPHINX_BUILD_DIR}/warning-log.txt
                         #-D "pngmath_latex=pdflatex"
                         #-D "pngmath_latex_preamble=\\\\pdfoutput 0"
                         "${SPHINX_BUILD_DIR}"
                         "${SPHINX_HTML_DIR}"
                         COMMENT "Building HTML documentation with Sphinx into ${SPHINX_BUILD_DIR}"
                         WORKING_DIRECTORY ${SPHINX_BUILD_DIR}
                         COMMAND
                         ${Python3_EXECUTABLE}
                         "${WSF_SPHINX_DIR}/build_command_index.py"
                         "${SPHINX_HTML_DIR}"
                         "${SPHINX_HTML_DIR}"
                        )

      add_custom_target(DOCUMENTATION_rebuild
                    COMMAND
                    ${SPHINX_EXECUTABLE}
                    -q -a -b html
                    -c "${SPHINX_BUILD_DIR}"
                    -d "${SPHINX_CACHE_DIR}"
                    "${SPHINX_BUILD_DIR}"
                    "${SPHINX_HTML_DIR}"
                    COMMENT "Building HTML documentation with Sphinx"
                    WORKING_DIRECTORY ${SPHINX_BUILD_DIR}
                    COMMAND
                    ${Python3_EXECUTABLE}
                    "${WSF_SPHINX_DIR}/build_command_index.py"
                    "${SPHINX_HTML_DIR}/docs"
                    "${SPHINX_BUILD_DIR}"
                   )
        set_property(TARGET DOCUMENTATION_rebuild PROPERTY FOLDER CMakeTargets)
        
        add_custom_target(DOCUMENTATION_LinkCheck
                    COMMAND
                    ${SPHINX_EXECUTABLE}
                    -q -b linkcheck
                    -c "${SPHINX_BUILD_DIR}"
                    -d "${SPHINX_CACHE_DIR}"
                    "${SPHINX_BUILD_DIR}"
                    "${SPHINX_HTML_DIR}"
                    COMMENT "Check documentation links with Sphinx"
                    WORKING_DIRECTORY ${SPHINX_BUILD_DIR}
                    COMMAND
                    ${Python3_EXECUTABLE}
                    "${WSF_SPHINX_DIR}/build_command_index.py"
                    "${SPHINX_HTML_DIR}"
                    "${SPHINX_HTML_DIR}"
                   )
        set_property(TARGET DOCUMENTATION_LinkCheck PROPERTY FOLDER CMakeTargets)
   endif()
endmacro()

macro(create_docfile)
   if (SPHINX_FOUND)
      add_wsf_doc_input(${WSF_SPHINX_DIR}) # Add the sphinx directory

      # Store global Sphinx properties in a local variables that will
      # configure conf.py.in
      get_property(WSF_SPHINX_INPUT GLOBAL PROPERTY WSF_SPHINX_INPUT)
      #get_property(WSF_SPHINX_EXCLUDE GLOBAL PROPERTY WSF_SPHINX_EXCLUDE)
      get_property(WSF_SPHINX_SIDEBAR_EXTS GLOBAL PROPERTY WSF_SPHINX_SIDEBAR_EXTS)

      # This message kept enabled as confirmation that Sphinx is being processed
      message(STATUS "Configuring Sphinx Documentation")

      # Sphinx doc paths for parsing in conf.py
      #set(SPHINX_DOC_PATHS "${WSF_OPTIONAL_PROJECT_DOCDIRS}")
      set(SPHINX_DOC_PATHS "${WSF_SPHINX_INPUT}")
      set(SPHINX_SIDEBARS_EXTS "${WSF_SPHINX_SIDEBAR_EXTS}")

      configure_file("${WSF_SPHINX_DIR}/conf.py.in"
                     "${SPHINX_BUILD_DIR}/conf.py"
                     @ONLY)
      configure_file("${WSF_SPHINX_DIR}/index.html"
                     "${SPHINX_BUILD_DIR}/index.html"
                     @ONLY)

      create_doctarget()
   endif()
endmacro()

# Install documentation HTML output in the 'install' location for the build. This macro
# depends on the WSF_INSTALL_DOCUMENTATION option set in the main CMakeLists.txt file.
macro(install_documentation)
   # For there to be documentation to install the build system must have Sphinx
   # installed and the optional DOCUMENTION target needs to be built
   if(WSF_INSTALL_DOCUMENTATION AND SPHINX_FOUND)
      if (NOT DOCUMENTATION_INSTALL_DIR)
         set (DOCUMENTATION_INSTALL_DIR "documentation")
      endif (NOT DOCUMENTATION_INSTALL_DIR)

      install(DIRECTORY ${CMAKE_BINARY_DIR}/documentation/html DESTINATION ${DOCUMENTATION_INSTALL_DIR} OPTIONAL COMPONENT Documentation)
      install(DIRECTORY ${CMAKE_BINARY_DIR}/documentation/pdf DESTINATION ${DOCUMENTATION_INSTALL_DIR} OPTIONAL COMPONENT Documentation)
      install(FILES ${WSF_SPHINX_DIR}/index-install.html DESTINATION ${DOCUMENTATION_INSTALL_DIR} RENAME index.html OPTIONAL COMPONENT Documentation)
   endif()
endmacro()
